#include "Collection_List.h"

#include "Log.h"
#include "PS_Log.h"

Collection_List::Collection_List() {
}

Collection_List::~Collection_List() {
    items->clear();
}

void Collection_List::append(Item *item) {
    bool was_empty = items.empty();
    items.push_back(item);
    if (was_empty)
        last = items->begin();
    else
        last++;

    LOG(INPUT) << "appended.  last:";
    (*last)->object->print(Log::output);
}

//
// Move one block of items (the source) just past the end of another
// (the destination), in the linked list of items.
//
void Collection_List::move_block(Collection_List& source, Collection_List& destination) {
    LOG_ENTER(OBJECT,"Collection_List::move_block");
    LOG(OBJECT) << "source:";
    source.write_IDs(Log::output); Log::output << "\n";
    LOG(OBJECT) << "destination:";
    destination.write_IDs(Log::output); Log::output << "\n";

    Item_Iterator dst       = destination.last;
    dst++;  // insert just after destination.last
    Item_Iterator src_first = source.start;
    Item_Iterator src_last  = source.last;
    src_last++; // must be one past the end

    LOG(OBJECT) << "pre-splice:"
                << " dst=ID " << (*dst)->ID
                << " src_first=ID " << (*src_first)->ID
                << " src_last=ID " << (*src_last)->ID;

    // Check if spans already adjacent on list.
    // If so, don't splice, 'cause I think list::splice has a bug here.
    bool doSplice = (*dst != *src_first);
    if (doSplice) {
        items.splice(dst, items, src_first, src_last);
    }

    LOG_EXIT();
}

int Collection_List::size() {
    return items.size();
}

void Collection_List::clear() {
    LOG_ENTER(OBJECT,"Collection_List::clear");

    items.clear();

    LOG_EXIT();
}

Collection_List_Iterator::Collection_List_Iterator(Collection& col, int index)
  : collection(col) {
    if (index == 0)
        iter = collection.start;
    else if (index == collection.n)
        iter = collection.end();
    else {
        iter = collection.begin();
        for (int i=0; i<collection.n && iter != collection.end(); i++)
            iter++;
    }
}

Item& Collection_List_Iterator::operator*() {
    return *iter;
}

iterator Collection_List_Iterator::operator++() {
    ++iter;
    return *this;
}

iterator Collection_List_Iterator::operator++(int) {
    Collection_List_Iterator clone(*this);
    ++iter;
    return *this;
}
